// 1. 定义核心类型（TS核心：类型约束，减少错误）
type StorageType = 'local' | 'session'; // 限制存储类型，只能是两个值
type SuccessCallback<T = void> = (result: T) => void; // 成功回调类型（支持泛型）
type FailCallback = (error: string) => void; // 失败回调类型

// 2. 旧存储工具（类型化，明确参数/返回值）
const OldStorage = {
  save: (
    key: string, 
    value: string, 
    success?: SuccessCallback<string>, 
    fail?: FailCallback
  ) => {
    try {
      localStorage.setItem(key, value);
      success?.('保存成功');
    } catch (err) {
      fail?.((err as Error).message); // TS类型断言，避免类型错误
    }
  },
  get: (
    key: string, 
    success?: SuccessCallback<string | null>, 
    fail?: FailCallback
  ) => {
    try {
      const value = localStorage.getItem(key);
      success?.(value);
    } catch (err) {
      fail?.((err as Error).message);
    }
  }
};

// 3. 新存储工具（类型化，参数/返回值清晰）
const NewStorage = {
  save: (
    storageType: StorageType, 
    key: string, 
    value: string
  ): Promise<string> => { // 明确返回Promise<string>
    return new Promise((resolve, reject) => {
      try {
        const storage = storageType === 'session' ? sessionStorage : localStorage;
        storage.setItem(key, value);
        resolve('保存成功');
      } catch (err) {
        reject((err as Error).message);
      }
    });
  },
  get: (
    storageType: StorageType, 
    key: string
  ): Promise<string | null> => { // 明确返回Promise<string | null>
    return new Promise((resolve, reject) => {
      try {
        const storage = storageType === 'session' ? sessionStorage : localStorage;
        const value = storage.getItem(key);
        resolve(value);
      } catch (err) {
        reject((err as Error).message);
      }
    });
  }
};

// 4. 适配器（严格遵循旧接口类型，防止参数错误）
const OldStorageAdapter = {
  save: async (
    key: string, 
    value: string, 
    success?: SuccessCallback<string>, 
    fail?: FailCallback
  ): Promise<void> => { // 明确返回Promise<void>
    try {
      const result = await NewStorage.save('local', key, value);
      success?.(result);
    } catch (err) {
      fail?.(err as string); // TS类型约束，确保err是string
    }
  },
  get: async (
    key: string, 
    success?: SuccessCallback<string | null>, 
    fail?: FailCallback
  ): Promise<void> => {
    try {
      const value = await NewStorage.get('local', key);
      success?.(value);
    } catch (err) {
      fail?.(err as string);
    }
  }
};

// 5. 旧业务代码（类型安全，编辑器有提示）
OldStorage.save = OldStorageAdapter.save;
OldStorage.get = OldStorageAdapter.get;

// 测试：TS会自动提示参数类型，错误传参直接报错
OldStorage.save(
  'username', // 必须是string，传number会报错
  'zhangsan', 
  (res) => console.log('旧调用成功：', res), // res自动提示是string
  (err) => console.log('旧调用失败：', err) // err自动提示是string
);

OldStorage.get(
  'username', 
  (val) => console.log('旧调用获取：', val), // val自动提示是string | null
  (err) => console.log('旧调用失败：', err)
);